package cn.wgoodq.study.MultiThreading;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

/**
 * 现在系统资源费配机制多数是资源抢占模式，谁先抢到谁先用。
 * 以继承Thread类的方式，实现多线程。
 */
class RunDemoThread {
    private static final Logger logger = LogManager.getLogger(RunDemoThread.class);

    /**
     * 线程控制之 join()
     */
    static void join() {

        for (int i = 0; i < 100; i++) {
            // 至当前进程的主线程（每个进程至少有一个线程，这个线程我称作主线程），每循环一次，输出一条记录。
            logger.info("{} -- {}", "thread0", i);
            if (i == 20) {
                // 此处启动第一个子线程，执行start()后，线程状态变为就绪状态，如果抢占到CPU资源就会执行DemoThread类中的run()方法。
                new DemoThread("thread1").start();
            }
            if (i == 30) {
                // 此处启动第二个子线程，时间走到此时，第一个子线程未必已经抢占到CPU资源开始执行，即，第二个子线程可能先于第一个子线程开始执行。
                new DemoThread("thread2").start();
            }
            /*if (i == 50) {
                DemoThread demoThread = new DemoThread("thread3");
                demoThread.start();
                try {
                    // 当主线程执行了第三个子线程的join()方法后，主线程会进入等待状态，等到第三个子线程执行完成后，主线程再继续进行执行。
                    // 但是这个操作对第一个和第二个子线程没有影响，他们会继续跟第三个子线程抢夺CPU资源，知道他们全部执行完毕。
                    demoThread.join();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }*/
            // run()和start()的区别。
            if (i == 70) {
                // 第四个子线程执行run()方法，效果和第三个子线程的方式一样。
                // 注释掉第三子线程相关代码，可以查看此部分代码效果。
                new DemoThread("thread4").run();
            }
        }
    }

    /**
     * 线程控制之 sleep()
     */
    static void sleep() throws InterruptedException {
        for (int i = 0; i < 100; i++) {
            logger.info(i);

            if (i == 10) {
                DemoThread demoThread = new DemoThread("thread1");
                demoThread.setName("demoThread");
                demoThread.start();

                logger.info("main go to sleep!");
                Thread.sleep(3);
                logger.info("main wake up!");
                if (demoThread.isAlive()) {
                    logger.info("demoThread go to sleep!");
                    // 此处并不能让demoThread线程去睡觉，被睡的还是主线程。
                    //noinspection AccessStaticViaInstance
                    demoThread.sleep(3);
                    logger.info("demoThread wake up!");
                } else {
                    logger.info("demoThread is completed");
                }
            }

        }
    }

    /**
     * 线程控制之 yield()
     * yield()方法在多核CPU效果不明显，因为你让出A核的资源并且被其他线程抢占了A核资源，但是你还可以去抢占B核资源。
     */
    static void yield() throws InterruptedException {

        YieldThread yieldThread1 = new YieldThread();
        YieldThread yieldThread2 = new YieldThread();

        yieldThread1.setPriority(Thread.MAX_PRIORITY);
        yieldThread2.setPriority(Thread.MIN_PRIORITY);

        yieldThread1.start();
        yieldThread2.start();

        // 通过Junit来运行此方法时，如果主线程先于子线程结束会出现强制中断子线程的问题，故此处让主线程等待子线程全部执行完毕。
        yieldThread1.join();
        yieldThread2.join();

    }
}